package com.fan.shop.businesslogic;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.fan.shop.domain.PurchaseOrder;
import com.fan.shop.global.ShopGlobalVariables;
import com.fan.shop.model.userclass.PurchaseLineUserClass;
import com.fan.shop.process.ProcExec;
import com.fan.shop.services.ItemService;
import com.fan.shop.services.PurchaseLineService;
import com.fan.shop.services.PurchaseOrderService;
import com.fan.shop.services.StockService;
import com.fan.shop.services.StoreService;
import com.fan.shop.services.TransactionReferenceService;
import com.fan.shop.services.UserService;

public class PurchaseOrderCreateProcess extends ProcExec<Integer> {

	private static Logger logger = Logger
			.getLogger(PurchaseOrderCreateProcess.class);
	private PurchaseOrderService purchaseOrderService;
	private PurchaseLineService purchaseLineService;
	private TransactionReferenceService transactionReferenceService;
	private StockService stockService;
	private UserService userService;
	private StoreService storeService;
	private ItemService itemService;
	private String poNumber;
	private String transactionCode;
	private String officerCode;
	private String storeCode;
	private Date transactionDate;
	private BigDecimal postage;
	private String status;
	private String buyer;
	private String deliveryAddress;
	private String comments;

	private List<PurchaseLineUserClass> attachedPOLines;

	public static Logger getLogger() {
		return logger;
	}

	public static void setLogger(Logger logger) {
		PurchaseOrderCreateProcess.logger = logger;
	}

	public PurchaseOrderService getPurchaseOrderService() {
		return purchaseOrderService;
	}

	public void setPurchaseOrderService(
			PurchaseOrderService purchaseOrderService) {
		this.purchaseOrderService = purchaseOrderService;
	}

	public PurchaseLineService getPurchaseLineService() {
		return purchaseLineService;
	}

	public void setPurchaseLineService(PurchaseLineService purchaseLineService) {
		this.purchaseLineService = purchaseLineService;
	}

	public TransactionReferenceService getTransactionReferenceService() {
		return transactionReferenceService;
	}

	public void setTransactionReferenceService(
			TransactionReferenceService transactionReferenceService) {
		this.transactionReferenceService = transactionReferenceService;
	}

	public StockService getStockService() {
		return stockService;
	}

	public void setStockService(StockService stockService) {
		this.stockService = stockService;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public StoreService getStoreService() {
		return storeService;
	}

	public void setStoreService(StoreService storeService) {
		this.storeService = storeService;
	}

	public ItemService getItemService() {
		return itemService;
	}

	public void setItemService(ItemService itemService) {
		this.itemService = itemService;
	}

	public String getPoNumber() {
		return poNumber;
	}

	public void setPoNumber(String poNumber) {
		this.poNumber = poNumber;
	}

	public String getTransactionCode() {
		return transactionCode;
	}

	public void setTransactionCode(String transactionCode) {
		this.transactionCode = transactionCode;
	}

	public String getOfficerCode() {
		return officerCode;
	}

	public void setOfficerCode(String officerCode) {
		this.officerCode = officerCode;
	}

	public String getStoreCode() {
		return storeCode;
	}

	public void setStoreCode(String storeCode) {
		this.storeCode = storeCode;
	}

	public Date getTransactionDate() {
		return transactionDate;
	}

	public void setTransactionDate(Date transactionDate) {
		this.transactionDate = transactionDate;
	}

	public BigDecimal getPostage() {
		return postage;
	}

	public void setPostage(BigDecimal postage) {
		this.postage = postage;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getBuyer() {
		return buyer;
	}

	public void setBuyer(String buyer) {
		this.buyer = buyer;
	}

	public String getDeliveryAddress() {
		return deliveryAddress;
	}

	public void setDeliveryAddress(String deliveryAddress) {
		this.deliveryAddress = deliveryAddress;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public List<PurchaseLineUserClass> getAttachedPOLines() {
		return attachedPOLines;
	}

	public void setAttachedPOLines(List<PurchaseLineUserClass> attachedPOLines) {
		this.attachedPOLines = attachedPOLines;
	}

	@Override
	public Integer processImpl() {

		if (purchaseOrderService.hasPurchaseOrder(poNumber)) {
			setErrorMessage("Purchase Order: " + poNumber + " already exists!");
			return ShopGlobalVariables.FAILED;
		}

		PurchaseOrder purchaseOrder = new PurchaseOrder();

		NewNumberGenerationProcess newNumberGenerationProcess = new NewNumberGenerationProcess();
		newNumberGenerationProcess.setTransactionCode(transactionCode);
		newNumberGenerationProcess
				.setTransactionReferenceService(transactionReferenceService);

		int result = newNumberGenerationProcess.process();
		if (result == ShopGlobalVariables.FAILED) {
			setErrorMessage(newNumberGenerationProcess.getErrorMessage());
			return ShopGlobalVariables.FAILED;
		} else {
			poNumber = newNumberGenerationProcess.getNewNumber();
		}

		purchaseOrder.setPoNumber(poNumber);
		purchaseOrder.setOfficerCode(officerCode);
		purchaseOrder.setStoreCode(storeCode);
		purchaseOrder.setTransactionDate(transactionDate);
		purchaseOrder.setPostage(postage);
		purchaseOrder.setStatus(ShopGlobalVariables.ENTERING);
		purchaseOrder.setBuyer(buyer);
		purchaseOrder.setDeliveryAddress(deliveryAddress);
		purchaseOrder.setComments(comments);
		purchaseOrder.setTransactionCode(transactionCode);

		for (PurchaseLineUserClass purchaseLineUserClass : attachedPOLines) {
			
			//validate stock
			PurchaseOrderLineValideProcess purchaseOrderLineValideProcess = new PurchaseOrderLineValideProcess();
			purchaseOrderLineValideProcess.setPoNumber(poNumber);
			purchaseOrderLineValideProcess.setItemService(itemService);
			purchaseOrderLineValideProcess.setPurchaseLineService(purchaseLineService);
			purchaseOrderLineValideProcess.setStockService(stockService);
			purchaseOrderLineValideProcess.setStoreService(storeService);
			purchaseOrderLineValideProcess.setStatus(ShopGlobalVariables.ENTERING);
			purchaseOrderLineValideProcess.setItemCode(purchaseLineUserClass.getItemCode());
			purchaseOrderLineValideProcess.setStoreCode(storeCode);
			purchaseOrderLineValideProcess.setPurchaseLineUserClass(purchaseLineUserClass);
			
			result = purchaseOrderLineValideProcess.process();
			
			if(result == ShopGlobalVariables.FAILED)
			{
				setErrorMessage(purchaseOrderLineValideProcess.getErrorMessage());
				return ShopGlobalVariables.FAILED;
			}
			
			
			//create purchase order line
			PurchaseOrderLineCreateProcess purchaseOrderLineCreateProcess = new PurchaseOrderLineCreateProcess();
			purchaseOrderLineCreateProcess.setPoNumber(poNumber);
			purchaseOrderLineCreateProcess.setItemCode(purchaseLineUserClass.getItemCode());
			purchaseOrderLineCreateProcess
					.setPrice(purchaseLineUserClass.getPrice());
			purchaseOrderLineCreateProcess.setQty(purchaseLineUserClass
					.getQuantity());
			purchaseOrderLineCreateProcess.setPurchaseLineService(purchaseLineService);
			
			result = purchaseOrderLineCreateProcess.process();
			if (result == ShopGlobalVariables.FAILED) {
				setErrorMessage(purchaseOrderLineCreateProcess
						.getErrorMessage());
				return ShopGlobalVariables.FAILED;
			}
			else
			{
				//update Stock
				StockHoldQtyUpdateProcess stockHoldQtyUpdateProcess = new StockHoldQtyUpdateProcess();
				stockHoldQtyUpdateProcess.setItemCode(purchaseLineUserClass.getItemCode());
				stockHoldQtyUpdateProcess.setStoreCode(storeCode);
				stockHoldQtyUpdateProcess.setStockService(stockService);
				stockHoldQtyUpdateProcess.setPoQuantity(purchaseLineUserClass.getQuantity());
				
				result = stockHoldQtyUpdateProcess.process();
				if(result == ShopGlobalVariables.FAILED)
				{
					setErrorMessage(stockHoldQtyUpdateProcess.getErrorMessage());
					return result;
				}
			}
		}
		
		purchaseOrderService.addPurchaseOrder(purchaseOrder);

		return ShopGlobalVariables.SUCCESS;
	}

}
